/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.live.luowang.MusicServie;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.session.PlaybackState;
import android.os.PowerManager;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaButtonReceiver;
import android.text.TextUtils;

import com.live.luowang.MyApplication;

import java.io.IOException;

import static android.media.MediaPlayer.OnCompletionListener;
import static android.media.MediaPlayer.OnErrorListener;
import static android.media.MediaPlayer.OnPreparedListener;
import static android.media.MediaPlayer.OnSeekCompleteListener;

/**
 * A class that implements local media playback using {@link MediaPlayer}
 */
public class Playback implements AudioManager.OnAudioFocusChangeListener,
        OnCompletionListener, OnErrorListener, OnPreparedListener, OnSeekCompleteListener {
    public static final float VOLUME_DUCK = 0.2f;
    public static final float VOLUME_NORMAL = 1.0f;
    private boolean canDuck=false;
    private final MusicService musicService;
    private int state=PlaybackState.STATE_STOPPED;
    private volatile boolean mAudioNoisyReceiverRegistered;
    private volatile int mCurrentPosition;
    private AudioManager audioManager;
    private MediaPlayer mediaPlayer;
    private String mCurrentMediaId;
    private Callback callback;

    public void setCallback(Callback callback) {
        this.callback = callback;
    }
    private IntentFilter mAudioNoisyIntentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);

    public Playback(MusicService service) {
        this.musicService = service;
        this.audioManager = (AudioManager) service.getSystemService(Context.AUDIO_SERVICE);
        ComponentName mbCN = new ComponentName(musicService.getPackageName(),MediaButtonReceiver.class.getName());
        audioManager.registerMediaButtonEventReceiver(mbCN);
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (mediaPlayer!=null && mediaPlayer.isPlaying()) {
                        Intent intent = new Intent();
                        intent.setAction("current");
                        intent.putExtra("current", mediaPlayer.getCurrentPosition());
                        musicService.sendBroadcast(intent);
                    }
                }
            }
        }).start();
    }

    public void stop() {
        state = PlaybackState.STATE_STOPPED;
        callback.onPlaybackStatusChanged(state);
        mCurrentPosition = getCurrentStreamPosition();
        giveUpAudioFocus();
        unregisterAudioNoisyReceiver();
        relaxResources();
    }

    public void setState(int state) {
        this.state = state;
    }

    public int getState() {
        return state;
    }

    public boolean isPlaying() {
        return mediaPlayer.isPlaying();
    }

    public int getCurrentStreamPosition() {
        return mediaPlayer != null ? mediaPlayer.getCurrentPosition() : mCurrentPosition;
    }

    public void play(MediaMetadataCompat metadata) {
        if(tryToGetAudioFocus()) {
            registerAudioNoisyReceiver();
            String mediaId = metadata.getDescription().getMediaId();
            boolean mediaHasChanged = !TextUtils.equals(mediaId, mCurrentMediaId);
            if (mediaHasChanged) {
                mCurrentPosition = 0;
                mCurrentMediaId = mediaId;
                MyApplication.setMediaId(mediaId);
                String source = metadata.getString(MediaMetadataCompat.METADATA_KEY_DATE);
                if (!source.startsWith("http://")){
                    source="http://luoo-mp3.kssws.ks-cdn.com"+source;
                }
                try {
                    createMediaPlayerIfNeeded();
                    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    mediaPlayer.setDataSource(source);
                    mediaPlayer.prepareAsync();
                } catch (IOException ex) {}
                state=PlaybackState.STATE_BUFFERING;
                callback.onPlaybackStatusChanged(state);
                callback.updateMetaDate(metadata);
            }else {
                if(mediaPlayer==null){
                    mediaPlayer = new MediaPlayer();
                    mediaPlayer.setWakeMode(musicService.getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
                    mediaPlayer.setOnPreparedListener(this);
                    mediaPlayer.setOnCompletionListener(this);
                    mediaPlayer.setOnErrorListener(this);
                    mediaPlayer.setOnSeekCompleteListener(this);
                }
                if (MyApplication.isMusicBar()){
                    callback.onPlaybackStatusChanged(state);
                    callback.updateMetaDate(metadata);
                    MyApplication.setIsMusicBar(false);
                    return;
                }
                if((state==PlaybackState.STATE_PAUSED || state==PlaybackState.STATE_STOPPED) && !mediaPlayer.isPlaying()) {
                    state=PlaybackState.STATE_PLAYING;
                    mediaPlayer.setVolume(0.2f,0.2f);
                    mediaPlayer.start();
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            float volume=0.2f;
                            for(int i=0;i<4;i++){
                                try {
                                    Thread.sleep(200);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                mediaPlayer.setVolume(volume,volume);
                                volume+=0.2f;
                            }
                        }
                    }).start();
                    callback.onPlaybackStatusChanged(state);
                    callback.updateMetaDate(metadata);
                }else if (state==PlaybackState.STATE_PLAYING){
                    callback.updateMetaDate(metadata);
                    state=PlaybackState.STATE_PLAYING;
                    callback.onPlaybackStatusChanged(state);
                }
            }
        }
    }
    public void pause() {
        if (mediaPlayer != null) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    float volume=0.8f;
                    for(int i=0;i<4;i++){
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        mediaPlayer.setVolume(volume,volume);
                        volume-=0.2f;
                    }
                    mediaPlayer.pause();
                    Intent intent=new Intent();
                    intent.setAction("musicPause");
                    musicService.sendBroadcast(intent);
                    mCurrentPosition = mediaPlayer.getCurrentPosition();
                    giveUpAudioFocus();
                    state = PlaybackState.STATE_PAUSED;
                    callback.onPlaybackStatusChanged(state);
                    unregisterAudioNoisyReceiver();
                }
            }).start();
        }
    }

    public void seekTo(int position) {
        mediaPlayer.seekTo(position);
        state = PlaybackState.STATE_BUFFERING;
        if (mediaPlayer == null) {
            mCurrentPosition = position;
        } else {
            if (mediaPlayer.isPlaying()) {
                state = PlaybackState.STATE_BUFFERING;
            }
            mediaPlayer.seekTo(position);
            callback.onPlaybackStatusChanged(state);
        }
    }

    private boolean tryToGetAudioFocus() {
        int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            return true;
        }
        return false;
    }

    private void giveUpAudioFocus() {
        audioManager.abandonAudioFocus(this);
    }

    @Override
    public void onAudioFocusChange(int focusChange) {
        switch (focusChange){
            case AudioManager.AUDIOFOCUS_GAIN:
                if(canDuck){
                    mediaPlayer.setVolume(VOLUME_NORMAL, VOLUME_NORMAL);
                }else {
                    if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
                        if (mCurrentPosition == mediaPlayer.getCurrentPosition()) {
                            mediaPlayer.start();
                            state = PlaybackState.STATE_PLAYING;
                        } else {
                            mediaPlayer.seekTo(mCurrentPosition);
                            state = PlaybackState.STATE_BUFFERING;
                        }
                    }
                }
                break;
            case AudioManager.AUDIOFOCUS_LOSS:
                if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                    stop();
                }
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                    pause();
                }
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                mediaPlayer.setVolume(VOLUME_DUCK, VOLUME_DUCK);
                canDuck=true;
                break;
        }
    }

    @Override
    public void onSeekComplete(final MediaPlayer mp) {
        mCurrentPosition = mp.getCurrentPosition();
        mediaPlayer.start();
        state = PlaybackState.STATE_PLAYING;
        callback.onPlaybackStatusChanged(state);
    }

    @Override
    public void onCompletion(MediaPlayer player) {
        callback.onCompletion();
    }

    @Override
    public void onPrepared(MediaPlayer player) {
        if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
            if (mCurrentPosition == mediaPlayer.getCurrentPosition()) {
                mediaPlayer.start();
                state = PlaybackState.STATE_PLAYING;
            } else {
                mediaPlayer.seekTo(mCurrentPosition);
                state = PlaybackState.STATE_BUFFERING;
            }
        }
        callback.onPlaybackStatusChanged(state);
        Intent intent=new Intent();
        intent.setAction("duration");
        intent.putExtra("duration",mediaPlayer.getDuration());
        musicService.sendBroadcast(intent);
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        if (extra==38) {
            callback.onError("来源拒绝访问");
        }
        return true;
    }

    private void relaxResources() {
        musicService.stopForeground(true);
        if (mediaPlayer != null) {
            if(mediaPlayer.isPlaying()){
                mediaPlayer.stop();
            }
            mediaPlayer.reset();
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

    private void registerAudioNoisyReceiver() {
        if (!mAudioNoisyReceiverRegistered) {
            musicService.registerReceiver(mAudioNoisyReceiver, mAudioNoisyIntentFilter);
            mAudioNoisyReceiverRegistered = true;
        }
    }

    private void unregisterAudioNoisyReceiver() {
        if (mAudioNoisyReceiverRegistered) {
            musicService.unregisterReceiver(mAudioNoisyReceiver);
            mAudioNoisyReceiverRegistered = false;
        }
    }

    private BroadcastReceiver mAudioNoisyReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
                if(mediaPlayer.isPlaying()){
                    mediaPlayer.pause();
                    intent.setAction("musicPause");
                    musicService.sendBroadcast(intent);
                }
            }
        }
    };

    private void createMediaPlayerIfNeeded() {
        if (mediaPlayer == null) {
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setWakeMode(musicService.getApplicationContext(),
                    PowerManager.PARTIAL_WAKE_LOCK);
            mediaPlayer.setOnPreparedListener(this);
            mediaPlayer.setOnCompletionListener(this);
            mediaPlayer.setOnErrorListener(this);
            mediaPlayer.setOnSeekCompleteListener(this);
        } else {
            mediaPlayer.reset();
        }
    }

    interface Callback {

        void onCompletion();

        void onPlaybackStatusChanged(int state);

        void onError(String error);

        void updateMetaDate(MediaMetadataCompat metadata);
    }
}
